/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.botthoughts;

import gnu.io.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.TooManyListenersException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Michael Shimniok
 */
public class SerialPanel extends javax.swing.JPanel implements SerialPortEventListener {

    /**
     * Creates new form SerialPanel
     */
    public SerialPanel() {
        initComponents();
        portToggle.setEnabled(false);
        //getPorts();
    }
    
    private void connect ( String portName ) throws Exception {
        //make sure port is not currently in use
        portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
        if ( portIdentifier.isCurrentlyOwned() ) {
            System.out.println("Error: Port is currently in use");
        } else {
            //create CommPort and identify available serial/parallel ports
            commPort = portIdentifier.open(this.getClass().getName(),2000);
            serialPort = (SerialPort) commPort;//cast all to serial
            //set baudrate, 8N1 stopbits, no parity
            serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
            //start I/O streams
            inputStream = serialPort.getInputStream();
            outputStream = serialPort.getOutputStream();
            open=true;        
        }
    }
    
    private void setBaud() {
        String newbaud = baudBox.getSelectedItem().toString();//get text from user
        //do simple check to make sure baudrate is valid
        baudRate=Integer.valueOf(newbaud).intValue();
    }
    
    
    /**
     * Gets a list of available serial ports and sticks those in the portBox JComboBox model
     */
    private void getPorts() {
        Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();
        portBox.removeAllItems();
        while ( portEnum.hasMoreElements() ) {
            portIdentifier = (CommPortIdentifier) portEnum.nextElement();
            if (portIdentifier.getPortType() == CommPortIdentifier.PORT_SERIAL) {
                portBox.addItem(portIdentifier.getName());
                System.out.println(portIdentifier.getName());
            }
        }
    }
    
    /**
     * when data is received from serial port, display the data on the terminal
     */
    @Override
    public void serialEvent(SerialPortEvent event) {
        if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
            byte[] buffer = new byte[MAX_DATA]; // create a buffer (enlarge if buffer overflow occurs)
            int numBytes;                       // how many bytes read (smaller than buffer)
            String s = "";

//            System.out.println("Serial event: DATA_AVAILABLE");
            
            try {
                numBytes = inputStream.read(buffer);
                s += new String(buffer).substring(0, numBytes);
//                System.out.println("<"+buffer[1]+">");
//                System.out.println("bytes " + Integer.toString(numBytes));
            } catch (IOException ex) {
                Logger.getLogger(SerialPanel.class.getName()).log(Level.SEVERE, null, ex);
            }
            
            if (myParser != null) {
                myParser.parseData(s);
            }
        }
    }
    
    public void setHandler(Parser p) {
        myParser = p;
    }
    
    /* call this from the main JFrame when it is closing, ensures disconnect of serial stuff */
    public void handleClose() {
            //when user closes, make sure to close open ports and open I/O streams
        if (portIdentifier != null && portIdentifier.isCurrentlyOwned()) { 
            try {
                //if port open, close port
                if (portToggle != null) {
                    portToggle.setText("Open Port");
                }
                if (inputStream != null) { //close input stream
                    inputStream.close();
                }
                if (outputStream != null) { //close output stream
                    outputStream.close();
                }
                if (serialPort != null) {
                    serialPort.removeEventListener();
                    serialPort.close();
                }
                open=false; 
            } catch (IOException ex) {
                Logger.getLogger(SerialPanel.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }        
    
    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        baudBox = new javax.swing.JComboBox();
        portBox = new javax.swing.JComboBox();
        portToggle = new javax.swing.JButton();

        setMaximumSize(new java.awt.Dimension(400, 25));
        setMinimumSize(new java.awt.Dimension(400, 25));
        setOpaque(false);
        setPreferredSize(new java.awt.Dimension(400, 25));
        setLayout(new java.awt.GridBagLayout());

        baudBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "2400", "4800", "9600", "14400", "19200", "38400", "57600", "115200" }));
        baudBox.setSelectedIndex(7);
        baudBox.setMaximumSize(new java.awt.Dimension(90, 25));
        baudBox.setMinimumSize(new java.awt.Dimension(90, 25));
        baudBox.setNextFocusableComponent(portBox);
        baudBox.setPreferredSize(new java.awt.Dimension(90, 25));
        baudBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                baudBoxActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 5);
        add(baudBox, gridBagConstraints);

        portBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Select Port" }));
        portBox.setMaximumSize(new java.awt.Dimension(150, 25));
        portBox.setMinimumSize(new java.awt.Dimension(150, 25));
        portBox.setPreferredSize(new java.awt.Dimension(150, 25));
        portBox.addPopupMenuListener(new javax.swing.event.PopupMenuListener() {
            public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {
                portBoxPopupMenuWillBecomeVisible(evt);
            }
            public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) {
            }
            public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) {
            }
        });
        portBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                portBoxActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 5);
        add(portBox, gridBagConstraints);

        portToggle.setText("Connect");
        portToggle.setMaximumSize(new java.awt.Dimension(110, 25));
        portToggle.setMinimumSize(new java.awt.Dimension(110, 25));
        portToggle.setPreferredSize(new java.awt.Dimension(110, 25));
        portToggle.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                portToggleActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 5);
        add(portToggle, gridBagConstraints);
    }// </editor-fold>//GEN-END:initComponents

    private void baudBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_baudBoxActionPerformed
        setBaud();
    }//GEN-LAST:event_baudBoxActionPerformed

    private void portBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_portBoxActionPerformed
        portName = (String)portBox.getSelectedItem();
        portToggle.setEnabled( portBox.getSelectedIndex() >= 0);
    }//GEN-LAST:event_portBoxActionPerformed

    private void portBoxPopupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {//GEN-FIRST:event_portBoxPopupMenuWillBecomeVisible
        getPorts(); // update the list of com ports dynamically
    }//GEN-LAST:event_portBoxPopupMenuWillBecomeVisible

    private void portToggleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_portToggleActionPerformed
        //only open valid port. portList[0]="select port" - not a valid port
        //if ((String)portBox.getSelectedItem() == portList[0]) {
        if (portBox.getSelectedIndex() < 0) {//.getSelectedItem().equals(portList[0])) {
            portToggle.setSelected(open);
            //JOptionPane.showMessageDialog(this, "Must Select Valid Port.", "Error", JOptionPane.ERROR_MESSAGE);
        }
        //if port open, close port & I/O streams
        else if (portIdentifier.isCurrentlyOwned()) { 
            portToggle.setText("Connect");
            portBox.setEnabled(true);
            baudBox.setEnabled(true);
            //close input stream
            if (inputStream != null) {
                try { inputStream.close();
                } catch (IOException ex) {
                    System.out.println("error "+ex.getMessage());
                }
            }
            //close output stream
            if (outputStream != null) {
                try { outputStream.close();
                } catch (IOException ex) {
                    System.out.println("error "+ex.getMessage());
                }
            }
            //close serial port
            System.out.println("closing serial port.");
            serialPort.removeEventListener();
            if (serialPort != null) {
                serialPort.close();
            }
            System.out.println("closed serial port.");

            open=false;
        } else {//else port is closed, so open it
            portToggle.setText("Disconnect");
            portBox.setEnabled(false);
            baudBox.setEnabled(false);
            try {
                connect(portName);
            }
            catch ( Exception e ) {
                System.out.println("error "+e.getMessage());
            }
            try {
                serialPort.addEventListener(this);
            } catch (TooManyListenersException ex) {
                System.out.println("error "+ex.getMessage());
            }
            serialPort.notifyOnDataAvailable(true);
        }
        System.out.println("end of toggle function");
    }//GEN-LAST:event_portToggleActionPerformed

    static int MAX_DATA = 1024;
    private String portName;
    private CommPort commPort;
    private SerialPort serialPort;
    private CommPortIdentifier portIdentifier = null;
    private InputStream inputStream;
    private OutputStream outputStream;
    private int baudRate=115200;
    private boolean open=false;
    private Parser myParser;
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JComboBox baudBox;
    private javax.swing.JComboBox portBox;
    private javax.swing.JButton portToggle;
    // End of variables declaration//GEN-END:variables
}
